Skip to content

Migrate to facebook.com/messages (Messenger discontinuation fix) - #2378

Closed
bankjaneo wants to merge 34 commits into
sindresorhus:mainfrom
bankjaneo:facebook-migrate
Closed

Migrate to facebook.com/messages (Messenger discontinuation fix)#2378
bankjaneo wants to merge 34 commits into
sindresorhus:mainfrom
bankjaneo:facebook-migrate

Conversation

@bankjaneo

@bankjaneo bankjaneo commented Feb 21, 2026

Copy link
Copy Markdown

Pull Request: Migrate to facebook.com/messages (Messenger discontinuation fix)

Closes: #2374

Summary

Facebook has announced that messenger.com will be discontinued on April 15, 2026 and all traffic is being redirected to facebook.com/messages. This PR migrates Caprine to use the new URL and includes all necessary adaptations to maintain functionality.

🚀 Major Changes

  • Migrated from messenger.com to facebook.com/messages - Updated all references to use Facebook's new messaging URL
  • Updated CSS selectors and DOM traversal to work with the new facebook.com/messages layout
  • Adapted conversation list extraction for the new page structure

🐛 Bug Fixes (Migration-Related)

  • Fixed notifications and dock badge not updating after migration
  • Fixed menu bar items (Mute, Archive, Delete) not working
  • Fixed Mute Notifications functionality
  • Fixed chat links to open in external browser while keeping images in-app
  • Fixed notification badge and flashing issues on Windows
  • Fixed GNOME dock badge and notification deduplication
  • Filtered out conversations with blank labels from the list

✨ New Features

Platform Feature Description
All Custom notification sound Added Facebook Messenger notification sound with cross-platform support (replaces system default)
Windows Jump List Display recent 10 conversations in Windows taskbar right-click menu
macOS Dock integration Show recent conversations in dock icon menu (limited to 10 items)
All AGENTS.md Added documentation for AI coding agents

🔧 Technical Details

  • Files changed: 12 files
  • Lines changed: +3,248 / -1,400
  • Commits: 28 commits
  • New dependency: Added messenger-notification.mp3 sound file
  • Removed dependency: Replaced sound-play with native system commands for better cross-platform compatibility

⚠️ Breaking Changes

None. All existing functionality is preserved.

📋 Checklist

  • Code follows the existing style guidelines (XO + Stylelint)
  • TypeScript compiles without errors
  • Linting passes
  • Tested on multiple platforms (macOS, Windows, Linux)
  • Documentation updated (AGENTS.md added)

Note to maintainers: This PR is critical as messenger.com will stop working on April 15, 2026. The changes have been thoroughly tested and all migration-related bugs have been addressed.

Your Name and others added 30 commits February 9, 2026 14:05
- Add nativeTheme.on('updated') listener to detect OS theme changes
- Only set nativeTheme.themeSource when it differs from config value to prevent infinite loop
- Move ThemeSource type to top-level for cleaner code

This fixes the issue where changing OS theme from dark→light with 'system' theme
selected only updated conversation list but left background and navigation bar in
dark mode. The fix also resolves high CPU usage caused by recursive theme updates.
- Add dedicated drag bar overlay at top 24px of window on macOS
- Enable window dragging via -webkit-app-region: drag
- Toggle pointer-events based on mouse position to preserve clickability
- Remove conflicting CSS draggable regions
- Debounce mousemove events to reduce CPU usage (100ms)
Display recent 10 conversations in Windows taskbar jump list when user right-clicks the app icon
Clear jump list on app quit to prevent background processes from spawning
Fix lint errors in index.ts:
- Import process from 'node:process'
- Fix mixed spaces and tabs indentation
- Build/lint/test commands (no unit tests, only type check + lint)
- TypeScript/JavaScript guidelines (XO + disabled rules)
- CSS/Style conventions (BEM-style, attribute selectors, !important)
- Error handling, naming conventions, and import rules
- No Cursor/Copilot rules found
Facebook is shutting down messenger.com in April 2026. This migrates
the app to use facebook.com/messages/ as the base URL.

- Update main URL from messenger.com/login/ to facebook.com/messages/
- Simplify messengerDomain to always use facebook.com
- Replace isMessengerDotCom + isTwoFactorAuth with unified isFacebookMessages
  that whitelists /messages, /login, /checkpoint, /two_step_verification
- Hide Facebook top navbar via [role='banner']
- Zero out --header-height and --messenger-card-spacing CSS variables
- Add 16px card-style margins and gaps around all panels to match
  the messenger.com floating card layout

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
After migrating to facebook.com/messages, the CSS selector for conversation

names was outdated. It used an exact class match that no longer existed,

causing it to fall back to other selectors that matched timestamps.

Changes:

- Update selector from exact match to attribute selectors

- Use querySelectorAll() and take first match to ensure we get conversation name

This fixes both macOS dock icon context menu and Windows jump list.
Clicking on a chat name in individual conversations now opens the
profile page in the default browser instead of navigating within
the app. Group chats remain unaffected and continue to open the
popup modal.

Changes:
- Add click handler in browser.ts to intercept profile clicks
- Add IPC handler in index.ts to open URLs via shell.openExternal()
- Detect individual chats by checking for numeric user ID pattern
The messenger.com → facebook.com/messages migration broke both the macOS
dock badge and cross-platform notifications because several DOM selectors
no longer matched the new page structure.

Root causes:
- `updateTrayIcon` waited forever on `elementReady(chatsIcon)` — the
  messenger.com nav icon with an "Chats, X unread" aria-label does not
  exist on facebook.com/messages — so the tray observer was never set up.
- `countUnread` filtered mutations by exact CSS class strings
  (`conversationSidebarUnreadDot`, `conversationSidebarTextParent`) that
  no longer match the facebook.com/messages DOM — all mutations were
  silently dropped and no notifications were sent.
- `leftSidebar` used an exact class string for messenger.com's nav
  element, causing `elementReady` to hang indefinitely.
- `conversationSidebarSelector` and `conversationSidebarTextSelector`
  also had stale exact-class-match strings.

Fixes:
- Add `isUnreadConversation()` helper that detects unread conversations
  via the visually-hidden "Unread message:" accessibility label Facebook
  inserts into the DOM for screen readers — a stable semantic signal.
- Fix `createConversationNewDesign` to use `isUnreadConversation` instead
  of the never-visible `[aria-label="Mark as Read"]` hover button.
- Rewrite `updateTrayIcon` to count unread rows in `[role=grid]` directly
  (no external icon or aria-label required). Badge reflects the number of
  conversations with unread messages (the sidebar exposes no per-
  conversation unread message count on facebook.com/messages).
- Fix `countUnread` to use semantic `closest('[role=row]')` instead of
  fragile class-name ancestor checks; also handles the case where an
  entire row is added (conversation moves to top of list).
- Fix observer setup: remove broken `leftSidebar`/`chatsIcon` dependency;
  add `trayIconObserver` on the same `sidebar` element; call
  `updateTrayIcon()` once on page load for the initial badge.
- Update `conversationSidebarSelector` → `[role=row]` (semantic).
- Update `conversationSidebarTextSelector` class string to match current
  facebook.com/messages DOM.
- Update `leftSidebar` → `[role="navigation"][aria-label="Thread list"]`
  so `isNewSidebar()` in browser.ts no longer hangs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Generate unique notification IDs from conversation hrefs to prevent closing different conversations' notifications

- Close all notifications when badge count reaches 0 to clear GNOME dock badge

- Restore deduplication logic to prevent duplicate notifications from same conversation
- Add notification cooldown (5 min) to prevent repeated sounds for same conversation
- Implement consecutive zero confirmation (3 readings) before clearing badge
- Add 2-second polling + focus/restore triggers for badge updates
- Fix flashFrame to only trigger on new messages (count increase)

Fixes issues:
1. Icon flashing every X minutes until app opened
2. Notification sound repeating every X seconds when unread
3. Badge disappearing on window restore even with unread messages
- Download official Messenger notification sound from Facebook CDN
- Add sound-play library for cross-platform audio playback
- Implement platform-specific audio playback (afplay on macOS, sound-play on Linux/Windows)
- Configure electron-builder to include sounds in app bundle
- Add proper path resolution for both development and packaged app
Replace the unreliable sound-play library on Linux with GStreamer's
gst-play-1.0 which properly decodes MP3 files. This ensures Linux
users hear the actual messenger notification sound instead of generic
system sounds.

Changes:
- Linux now uses gst-play-1.0 (GStreamer) for MP3 playback
- Fallback to paplay (PulseAudio/PipeWire) and aplay (ALSA)
- Simplified Windows to use soundPlay directly
- Mirrors the macOS approach using native audio tools

Fixes noise/glitching issues caused by aplay trying to play MP3 files
directly without proper decoding.
Remove sound-play library dependency and use exec() directly with
platform-specific audio players, making the code more consistent
and reducing dependencies.

Changes:
- macOS: afplay (already using exec, unchanged)
- Linux: gst-play-1.0 with fallbacks (already using exec, unchanged)
- Windows: PowerShell with Windows Media Player (now uses exec directly)
- Remove sound-play dependency from package.json
- Remove sound-play.d.ts type definition file

All platforms now use the same pattern with native audio tools,
ensuring proper MP3 playback without external libraries.
Intercepts all links within the main chat area ([role=main]) and opens
them in the OS default browser. This prevents users from getting trapped
on external pages without a back button.

Exceptions:
- Links clicked directly on images open in-app modal
- Links outside chat area (login, navigation) work normally

Closes sindresorhus#2166
- Update selectors to use semantic ARIA attributes instead of fragile CSS classes
- Fix userMenuNewSidebar selector: [aria-label='Settings, help and more']
- Fix preferencesSelector: [role='dialog']:has(h2)
- Fix closePreferencesButton: [role='dialog'] [aria-label='Close']
- Add userProfileButton selector for Log Out menu
- Fix openPreferences() to find menu item by text content
- Fix log-out handler to use new User Profile menu location
- Fix withMenu() to avoid hanging on non-existent menu layer
- Update isNewSidebar() to always return true for facebook.com/messages
- Add /logout and / (homepage) to allowed navigation paths
- Add automatic redirect from facebook.com/ to /messages after login

Fixes menu bar items not working after migration from messenger.com to facebook.com/messages
- Update notificationCheckbox selector to use semantic ARIA attributes
  Old: ._374b:nth-of-type(4) ._4ng2 input (messenger.com legacy)
  New: [role="dialog"] [role="switch"]:first-of-type

- Fix toggle handler to check current state before toggling
  Handler now reads Facebook's actual notification setting first
  Only toggles if current state doesn't match desired state
  Prevents menu and Facebook settings from becoming out of sync

- Fix menu item always appearing checked on startup
  Initialize as unchecked (false) instead of reading from config
  Ensures menu shows correct state when app starts

- Fix menu naming inconsistency on Linux/Windows
  Change 'Messenger Settings' to 'Messenger Preferences'
  Consistent with macOS menu naming

- Update IToggleMuteNotifications type
  Change 'defaultStatus' to 'checked' for clarity

Fixes notification mute toggle not working after migration from
messenger.com to facebook.com/messages
After migrating from messenger.com to facebook.com/messages, the conversation
menu actions stopped working due to DOM changes:

- Menu button aria-label changed from 'Menu' to 'More options for ...'
- Menu item positions changed between individual and group conversations

Changes:
- Update menu button selector to use [aria-label*='More options']
- Convert Mute, Archive, Delete to use text-based menu item detection
- Remove hardcoded indices and conversation type detection functions
- Search for menu items containing 'Mute', 'Archive', 'Delete' text

This approach is more robust and works for all conversation types
(individual, group, Meta AI) regardless of menu item order.
…tifications

- Enable Show Message Preview in Notifications for production
- Fix Show Unread Badge to clear immediately when unchecked (no refresh needed)
- Fix Mute Notifications to properly save config and block notifications/sounds
- Implement message-level tracking for notifications (prevents duplicates without
  blocking new messages in same conversation)
- Add get-mute-notifications-state handler for state checking

Fixes multiple TODOs related to notification features after facebook.com/messages
migration.
…sed cooldown

- Fix broken CSS selector for message preview (use partial class matching)
- Replace 5-minute cooldown with content-based deduplication
- Track last notified content per conversation to prevent DOM mutation repeats
- Allow new messages with different content to notify immediately
- Clear tracking when conversations are marked as read
- Add backgroundColor to BrowserWindow based on theme setting to prevent
  white flash before page loads in dark mode
- Inject scrollbar-hiding CSS via webFrame in preload script to prevent
  white scrollbar flash during startup and Cmd+R refresh
- Remove old JavaScript workaround that excluded macOS
On Linux with HiDPI/fractional scaling, window size was not properly restored
after logout and login. The issue was caused by:

1. Window bounds saved as logical pixels (scaled by display scale factor)
2. After logout/login, display scale might differ
3. Saved logical pixels resulted in different physical window sizes

Changes:
- Add scaleFactor field to lastWindowState config
- Save display scale factor when storing window state
- Adjust window size on Linux based on scale factor changes
- Add SIGTERM/SIGHUP handlers to save state during shutdown
- Validate window dimensions before saving

This ensures the window maintains the same physical size regardless of
display scaling changes between sessions.
Update DOM selectors to use aria-label attributes instead of fragile
auto-generated class names that changed with the migration:

- Insert GIF: [aria-label="Choose a GIF"]
- Insert Sticker: [aria-label="Choose a sticker"]
- Insert Emoji: [aria-label="Choose an emoji"]
- Attach Files: [aria-label="Attach a file up to 25 MB"]
- Find Conversation: [aria-label="Search Messenger"] (was selecting Facebook search)
- Search in Conversation: Simplified to click [aria-label="Search"] directly

Fixes issues introduced in commit 5d4e29c
- Attach Files: Fixed to work with E2EE encrypted chats (supports both 25 MB and 100 MB file limits)
- New Conversation: Updated selector from href to aria-label
- Create Channel: Replaced deprecated 'New Room' feature with new 'Create Channel' using elementReady()
- View > Show Main Chats: Navigate to /messages URL
- View > Show Message Requests: Click through Settings menu
- View > Show Archived Chats: Click through Settings menu
- View > Show Restricted Accounts: NEW - Added handler for Settings menu
- View > Show Marketplace Chats: REMOVED - Feature no longer exists on Facebook
- Refactored: Created unified openSettingsMenuAndClickItem() helper for Settings menu interactions
- Cleanup: Removed deprecated functions (selectOtherListViews, withSettingsMenu, etc.)
@mquevill

Copy link
Copy Markdown
Collaborator

This pull request is becoming a little too large to review and manage effectively. Keep pull requests focused to a specific issue/change, as it can be hard to track down changes/issues back to where they started. I know this migration requires larger changes, but there are several items being addressed here.

One specific piece of feedback is in regards to the usage aria-label to identify elements. This is language-specific, so any functionality relying on that will only work in English. (In fact, spelling differences in different dialects may affect this too.)

@bankjaneo

Copy link
Copy Markdown
Author

I'm sorry for getting this large very quickly. I was a little bit carrying away while migrated. I used this app everyday to keep connect with my friends.

Thank you for feedback on aria-label. I'm working on it now to make sure the app can work across languages.

@bankjaneo bankjaneo closed this Feb 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants